package com.android.miniskirt.service;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.proxy.ProxyInfo;
import org.jivesoftware.smack.proxy.ProxyInfo.ProxyType;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.provider.DelayInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.pubsub.provider.EventProvider;
import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
import org.jivesoftware.smackx.pubsub.provider.ItemsProvider;
import org.jivesoftware.smackx.pubsub.provider.PubSubProvider;

import com.android.miniskirt.miniApplication;
import com.android.miniskirt.broadcastreceiver.MiniBroadcastReceiver;
import com.android.miniskirt.service.miniXmppConnection;

import android.app.NotificationManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;

public class miniService extends Service
{
	private miniXmppConnection mConnection;
    private ConnectionConfiguration mConnectionConfiguration;
    private NotificationManager mNotificationManager;
    private SharedPreferences mSettings;
    private ProxyInfo mProxyInfo;
    private boolean mUseProxy;
    private static final String TAG = "MiniService";
    private static final int DEFAULT_XMPP_PORT = 5222;
    private String mLogin;
    private String mPassword;
    private String mHost;
    private String mService;
    private int mPort;
    private final IBinder mBinder = new miniBinder();
    private MiniBroadcastReceiver mReceiver = new MiniBroadcastReceiver();
    private MiniServiceBroadcastReceiver mOnOffReceiver = new MiniServiceBroadcastReceiver();
    private MiniServicePreferenceListener mPreferenceListener = new MiniServicePreferenceListener();

    private boolean mOnOffReceiverIsRegistered;
	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		//return super.onUnbind(intent);
		if (!mConnection.getAdaptee().isConnected()) {
		    this.stopSelf();
		}
		return true;
	}
	/* (non-Javadoc)
	 * @see android.app.Service#onCreate()
	 */
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
		mSettings = PreferenceManager.getDefaultSharedPreferences(this);
		mSettings.registerOnSharedPreferenceChangeListener(mPreferenceListener);
		if (mSettings.getBoolean("settings_away_chk", false)) {
		    mOnOffReceiverIsRegistered = true;
		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
		}
		String tmpJid = mSettings.getString(miniApplication.ACCOUNT_USERNAME_KEY, "").trim();
		mLogin = StringUtils.parseName(tmpJid);
		mPassword = mSettings.getString(miniApplication.ACCOUNT_PASSWORD_KEY, "");
		mPort = DEFAULT_XMPP_PORT;
		mService = StringUtils.parseServer(tmpJid);
		mHost = mService;

		if (mSettings.getBoolean("settings_key_specific_server", false)) {
		    mHost = mSettings.getString("settings_key_xmpp_server", "").trim();
		    if ("".equals(mHost))
			mHost = mService;
		    String tmpPort = mSettings.getString("settings_key_xmpp_port", "5222");
		    if (!"".equals(tmpPort))
			mPort = Integer.parseInt(tmpPort);
		}
		if (mSettings.getBoolean(miniApplication.FULL_JID_LOGIN_KEY, false) ||
		    "gmail.com".equals(mService) || "googlemail.com".equals(mService))  {
		    mLogin = tmpJid;
		}

		initConnectionConfig();
		configure(ProviderManager.getInstance());

		mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		mConnection = new miniXmppConnection(mConnectionConfiguration, tmpJid, mLogin, mPassword, this);

//		Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
//		mBind = new miniXmppFacade(mConnection);
		Log.d(TAG, "ONCREATE");
	}
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return mBinder;
	}
	/* (non-Javadoc)
	 * @see android.app.Service#onStart(android.content.Intent, int)
	 */
	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onStart");
		try {
		    mConnection.connectAsync();
		} catch (RemoteException e) {
		    e.printStackTrace();
		}
	}
    @Override
    public void onDestroy() {
	super.onDestroy();
	mNotificationManager.cancelAll();
	unregisterReceiver(mReceiver);
	mSettings.unregisterOnSharedPreferenceChangeListener(mPreferenceListener);
	if (mOnOffReceiverIsRegistered)
	    unregisterReceiver(mOnOffReceiver);
//	if (mConnection.isAuthentificated() && BeemConnectivity.isConnected(this))
	    mConnection.disconnect();
	Log.d(TAG, "ONDESTROY");
    }
	public class miniBinder extends Binder {
		public miniService getService()
		{
			return miniService.this;
		}
	}//miniBinder

    //Constructor
    public miniService (){
    	
    }
    /**
     * Initialize the connection.
     */
    private void initConnectionConfig() {
	// TODO add an option for this ?
    // SmackConfiguration.setPacketReplyTimeout(30000);
	mUseProxy = mSettings.getBoolean(miniApplication.PROXY_USE_KEY, false);
	if (mUseProxy) {
	    String stype = mSettings.getString(miniApplication.PROXY_TYPE_KEY, "HTTP");
	    String phost = mSettings.getString(miniApplication.PROXY_SERVER_KEY, "");
	    String puser = mSettings.getString(miniApplication.PROXY_USERNAME_KEY, "");
	    String ppass = mSettings.getString(miniApplication.PROXY_PASSWORD_KEY, "");
	    int pport = Integer.parseInt(mSettings.getString(miniApplication.PROXY_PORT_KEY, "1080"));
	    ProxyInfo.ProxyType type = ProxyType.valueOf(stype);
	    mProxyInfo = new ProxyInfo(type, phost, pport, puser, ppass);
	} else {
	    mProxyInfo = ProxyInfo.forNoProxy();
	}
	if (mSettings.getBoolean("settings_key_specific_server", false))
	    mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort, mService, mProxyInfo);
	else
	    mConnectionConfiguration = new ConnectionConfiguration(mService, mProxyInfo);

	if (mSettings.getBoolean("settings_key_xmpp_tls_use", false)
	    || mSettings.getBoolean("settings_key_gmail", false)) {
	    mConnectionConfiguration.setSecurityMode(SecurityMode.required);
	}
	if (mSettings.getBoolean(miniApplication.SMACK_DEBUG_KEY, false))
	    mConnectionConfiguration.setDebuggerEnabled(true);
	mConnectionConfiguration.setSendPresence(true);
	// maybe not the universal path, but it works on most devices (Samsung Galaxy, Google Nexus One)
	mConnectionConfiguration.setTruststoreType("BKS");
	mConnectionConfiguration.setTruststorePath("/system/etc/security/cacerts.bks");
    }
    
    /**
     * Get the notification manager system service.
     *
     * @return the notification manager service.
     */
    public NotificationManager getNotificationManager() {
	return mNotificationManager;
    }
    public void initJingle(XMPPConnection adaptee) {
    }
    private void configure(ProviderManager pm) {
    	Log.d(TAG, "configure");
    	// Service Discovery # Items
    	pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
    	// Service Discovery # Info
    	pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());

    	// Privacy
    	//pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
    	// Delayed Delivery only the new version
    	pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInfoProvider());

    	// Service Discovery # Items
    	pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
    	// Service Discovery # Info
    	pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());

    	// Chat State
    	ChatStateExtension.Provider chatState = new ChatStateExtension.Provider();
    	pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState);
    	pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates",
    	    chatState);
    	pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState);
    	pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState);
    	pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState);
    	// capabilities
//    	pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsProvider());
    	//Pubsub
    	pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider());
    	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
    	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
    	pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider());

    	pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider());
    	pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider());
    	pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider());
    	//TODO rajouter les manquants pour du full pubsub


    	//PEP avatar
//    	pm.addExtensionProvider("metadata", "urn:xmpp:avatar:metadata", new AvatarMetadataProvider());
//    	pm.addExtensionProvider("data", "urn:xmpp:avatar:data", new AvatarProvider());
        }
    /**
     * Get the preference of the service.
     * @return the preference
     */
    public SharedPreferences getServicePreference() {
	return mSettings;
    }
    /**
     * Listen on some Intent broadcast, ScreenOn and ScreenOff.
     */
    private class MiniServiceBroadcastReceiver extends BroadcastReceiver {

	private String mOldStatus;
	private int mOldMode;

	/**
	 * Constructor.
	 */
	public MiniServiceBroadcastReceiver() {
	}

	@Override
	public void onReceive(final Context context, final Intent intent) {
	    String intentAction = intent.getAction();
//	    if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) {
//		mOldMode = mConnection.getPreviousMode();
//		mOldStatus = mConnection.getPreviousStatus();
//		if (mConnection.isAuthentificated())
//		    mConnection.changeStatus(Status.CONTACT_STATUS_AWAY,
//			    mSettings.getString("settings_away_message", "Away"));
//	    } else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) {
//		if (mConnection.isAuthentificated())
//		    mConnection.changeStatus(mOldMode, mOldStatus);
	    }
	}
    /**
     * Listen on preference changes.
     */
    private class MiniServicePreferenceListener implements SharedPreferences.OnSharedPreferenceChangeListener {

	/**
	 * ctor.
	 */
	public MiniServicePreferenceListener() {
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
	    if ("settings_away_chk".equals(key)) {
		if (sharedPreferences.getBoolean("settings_away_chk", false)) {
		    mOnOffReceiverIsRegistered = true;
		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
		    registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
		} else {
		    mOnOffReceiverIsRegistered = false;
		    unregisterReceiver(mOnOffReceiver);
		}
	    }
	}
    }
}//miniService

